package com.hp.goods_service.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hp.goods_service.entity.Goods;
import com.hp.goods_service.mapper.GoodsMapper;
import com.hp.goods_service.service.IGoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@CacheConfig(cacheNames = "Goods")
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements IGoodsService {

    @Autowired
    private GoodsMapper goodsMapper;

    @Cacheable(key = "T(String).valueOf(#id)")
    @Override
    public Goods getGoodsById(Long id) {
        return goodsMapper.selectById(id);
    }

    @Cacheable(cacheNames = "GoodsPage",key = "T(String).valueOf(#page.current)")
    @Override
    public IPage<Goods> getGoodsPage(Page<Goods> page) {
        return goodsMapper.selectGoodsPage(page);
    }

    @CachePut(key = "T(String).valueOf(#goods.id)")
    @CacheEvict(cacheNames = "GoodsPage",allEntries = true)
    @Override
    public Goods saveGoods(Goods goods) {
        goodsMapper.insert(goods);
        return goods;
    }

    @CachePut(key = "T(String).valueOf(#goods.id)")
    @CacheEvict(cacheNames = "GoodsPage",allEntries = true)
    @Override
    public Goods updateGoods(Goods goods) {
        goodsMapper.updateById(goods);
        return goods;
    }

    @Caching(evict = {
            @CacheEvict(key = "T(String).valueOf(#id)"),
            @CacheEvict(cacheNames = "GoodsPage",allEntries = true)
    })
    @Override
    public void removeGoods(Long id) {
        goodsMapper.deleteById(id);
    }

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    public Boolean buy(){
        Boolean bool = redisTemplate.execute(new SessionCallback<Boolean>() {
            @Override
            public Boolean execute(RedisOperations redisOperations) throws DataAccessException {
                //监控商品的库存，开启乐观锁
                redisOperations.watch("goods_num");
                int goodsNum = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get("goods_num")));
                if(goodsNum == 0){
                    log.info("商品已售完");
                    return false;
                }
                //启动事务
                redisOperations.multi();
                //没有售完，就减少库存
                redisTemplate.opsForValue().increment("goods_num",-1);
                //提交事务
                List list = redisOperations.exec();
                if(list == null || list.size() == 0){
                    log.info("购买失败");
                    return false;
                }
                log.info("购买成功！" + list.get(0));
                return true;
            }
        });
        return bool;
    }

//    public static final String TYPE = "GOODS-";
//
//    @Autowired
//    private RedisTemplate<String,Object> redisTemplate;
//
//    public Goods getGoodsById(Long id){
//        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
//        Object value = ops.get(TYPE + id);
//        //外层先读缓存，缓存如果有，就不执行同步块
//        if(value == null) {
//            synchronized (this) {
//                //1） 以id为键查询Redis缓存，如果能查到就返回数据，结束
//                value = ops.get(TYPE + id);
//                //2）如果查不到，就查询数据库
//                if (value == null) {
//                    System.out.println("缓存不存在，查询数据库");
//                    // 数据库查到，缓存到Redis,返回
//                    Goods goods = this.getById(id);
//                    if (goods != null) {
//                        System.out.println("数据库存在，保存到缓存");
//                        ops.set(TYPE + id, goods);
//                    } else {
//                        System.out.println("数据库不存在，返回null");
//                        //保存空数据到缓存中，设置过期时间
//                        ops.set(TYPE + id,new Goods(),30, TimeUnit.SECONDS);
//                    }
//                    return goods;
//                } else {
//                    System.out.println("缓存存在，返回" + value);
//                    //如果能查到就返回数据，结束
//                    return (Goods) value;
//                }
//            }
//        }
//        System.out.println("缓存存在，返回" + value);
//        return (Goods) value;
//    }
}
